#include <jni.h>
#include <stdlib.h>
#include <math.h>
#include <sys/time.h>
#include <time.h>
#include <android/log.h>
#include <stdint.h>
#include "importgl.h"
#include "mybitmap.h"
#define  LOG_TAG    "app-android"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

#ifdef __cplusplus
extern "C" {
#endif
#define PI 3.1415926535897932f
#define SCROLL_ACTION 1
#define SCALE_ACTION 2
static int  sWindowWidth  = 320;
static int  sWindowHeight = 480;
static GLfloat lPadding = 0;
static GLfloat tPadding = 0;
static GLfloat scrollX = 0;
static GLfloat scrollY = 0;
static GLfloat scaleX = 1;
static GLfloat scaleY = 1;
static GLfloat scaleX_fixed = 1;
static GLfloat scaleY_fixed = 1;
static GLfloat adjustX = 0;
static GLfloat adjustY = 0;

static void appInit();
static void appDeinit();
static void drawBitmap();
static int appRender();
static void prepareFrame(int width, int height);
static GLfloat* vertex;
static GLfloat* colors;

static void glDataInit()
{
	LOGI("glDataInit");
	bitmap = historyStack->header->bitmap;
	int i=0;
    int j=0;
    unsigned char* p = bitmap->pixels;
    int w = bitmap->width;
    int h = bitmap->height;
    int len = w*h;
    vertex =(GLfloat*)malloc(sizeof(GLfloat)*len*2);
    colors =(GLfloat*)malloc(sizeof(GLfloat)*len*4);
    //LOGI("w:%d, h:%d",w,h);
    for(i=0; i<h; i++)
    {
		for(j=0; j<w; j++)
        {
			unsigned char a,r,g,b;
            int offset = bitmap->unpack(p,&a,&r,&g,&b);
            p += offset;
            //LOGI("argb:%d.%d.%d.%d",a,r,g,b);
            vertex[(i*w+j)*2] = j;
            vertex[(i*w+j)*2+1] = i;

            colors[(i*w+j)*4] = r/255.0;
            colors[(i*w+j)*4+1] = g/255.0;
            colors[(i*w+j)*4+2] = b/255.0;
            colors[(i*w+j)*4+3] = a/255.0;
        }
	}
}

static void appInit()
{
    glEnable(GL_NORMALIZE);
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);
    glShadeModel(GL_FLAT);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glDataInit(bitmap);
}

static void  appDeinit()
{
	free(vertex);
    free(colors);
}

static int appRender()
{
	prepareFrame(sWindowWidth, sWindowHeight);
	drawBitmap(bitmap);
}

static void prepareFrame(int width, int height)
{
    glViewport(0, 0, width, height);
    glClearColorx((GLfixed)(0.1f * 65536),
				  (GLfixed)(0.2f * 65536),
                  (GLfixed)(0.3f * 65536), 0x10000);
    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrthof(0,width,height,0,1,-1);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(tPadding+scrollX+adjustX, lPadding+scrollY+adjustY,0);
    glScalef(scaleX_fixed*scaleX,scaleY_fixed*scaleY,1);
    glPointSize(scaleX_fixed*scaleX);
}

static void drawBitmap()
{
	int i=0;
	int j=0;
	int w = bitmap->width;
	int h = bitmap->height;
	for(i=0; i<h; i++)
	{
      	glVertexPointer(2, GL_FLOAT, 0, vertex+i*w*2);
		glColorPointer(4, GL_FLOAT, 0,colors+i*w*4);
		glDrawArrays(GL_POINTS, 0,w);
	}
	//LOGI("drawing code: %d",glGetError());
	glFinish();
}

void
Java_com_npsngs_hawkeye_MyGLSurfaceView_nativeInit( JNIEnv*  env ,jclass cls)
{
    importGLInit();
    appInit();
}

void
Java_com_npsngs_hawkeye_MyGLSurfaceView_nativeResize( JNIEnv*  env, jclass cls, jint w, jint h )
{
    sWindowWidth  = w;
    sWindowHeight = h;
    if(bitmap->height < sWindowHeight
       ||bitmap->width < sWindowWidth)
    {
		lPadding = (sWindowHeight-bitmap->height)/2;
        tPadding = (sWindowWidth-bitmap->width)/2;
    }

    __android_log_print(ANDROID_LOG_INFO, "app-android.c", "resize w=%d h=%d", w, h);
}

/* Call to finalize the graphics state */
void
Java_com_npsngs_hawkeye_MyGLSurfaceView_nativeDone( JNIEnv*  env )
{
    appDeinit();
    importGLDeinit();
}

/* Call to render the next GL frame */
void
Java_com_npsngs_hawkeye_MyGLSurfaceView_nativeRender( JNIEnv*  env ,jclass cls)
{
    appRender();
}

void
Java_com_npsngs_hawkeye_MyGLSurfaceView_nativeOnScroll( JNIEnv*  env ,jclass cls ,jfloat x,jfloat y)
{
	LOGI("native_scroll x:%f y:%f",x,y);
	scrollX = x;
	scrollY = y;
}

void
Java_com_npsngs_hawkeye_MyGLSurfaceView_nativeOnScale( JNIEnv*  env ,jclass cls ,jfloat x,jfloat y, jfloat centerX, jfloat centerY)
{
    scaleX = x;
    scaleY = y;
	
	adjustX = (centerX-tPadding-scrollX)*(1-scaleX);
	adjustY = (centerY-lPadding-scrollY)*(1-scaleY);
	LOGI("native_scale dx:%f dy:%f centerX:%f centerY:%f adjustX:%f adjustY:%f",x,y,centerX,centerY,adjustX,adjustY);
}

void
Java_com_npsngs_hawkeye_MyGLSurfaceView_nativeActCancel( JNIEnv*  env ,jclass cls, jint actionType)
{
	LOGI("Native_Cancel action:%d",actionType);
    switch(actionType)
	{
		case SCROLL_ACTION:
			tPadding += scrollX;
			lPadding += scrollY;
			scrollX = 0;
			scrollY = 0;
			break;
		case SCALE_ACTION:
			scaleX_fixed *= scaleX;
			scaleY_fixed *= scaleY;
			tPadding += adjustX;
			lPadding += adjustY;
			adjustX = 0;
			adjustY = 0;
			scaleX = 1;
			scaleY = 1;
			break;
		default:
			break;
	}	

}

void Java_com_npsngs_hawkeye_MyGLSurfaceView_nativeGLReset( JNIEnv*  env ,jclass cls)
{
	lPadding = 0;
	tPadding = 0;
	if(bitmap->height < sWindowHeight || bitmap->width < sWindowWidth)
    	{
        	lPadding = (sWindowHeight-bitmap->height)/2;
        	tPadding = (sWindowWidth-bitmap->width)/2;
    	}

	scrollX = 0;
	scrollY = 0;
	scaleX = 1;
	scaleY = 1;
	scaleX_fixed = 1;
	scaleY_fixed = 1;
}

void Java_com_npsngs_hawkeye_MainActivity_nativeGraying( JNIEnv*  env ,jclass cls, jfloat r,jfloat g, jfloat b)
{
	int ret = graying(r,g,b);
	if(-1 == ret)
	appInit();
}

void Java_com_npsngs_hawkeye_MainActivity_nativeBinaryzation( JNIEnv*  env ,jclass cls, jint theshold)
{
	int ret = binaryzation(theshold);
    if(-1 == ret)
    appInit();
}

#ifdef __cplusplus
}
#endif
